<template>
  <q-page class="q-pa-md" v-loading="loading">
    <div style="position: relative; ">
      <q-breadcrumbs class="q-mb-md" style="height:50px;line-height: 40px; border-bottom: 1px dashed #ccc;">
        <q-breadcrumbs-el :label="$t('operatorManagement')" />
      </q-breadcrumbs>
      <el-row :gutter="20" class="bgBox">
        <el-col :span="4" class="leftMenus">
          <el-button type="primary" size="default" @click=" openDialogAddOperator()"
            style="width: 100%; margin: 0 0 10px 0;">{{ $t('addOperatorClassification') }}</el-button>
          <div class="row">
            <el-input v-model.trim="operator" class="w-50 m-2" placeholder="搜索" @keyup.enter="searchOperator()" />
          </div>
          <main id="stencil-container" class="toolbox">
            <el-tree ref="treeRef" :data="treeData" node-key="id" :default-expand-all="true" :expand-on-click-node="false"
              :filter-node-method="filterNode" :props="{
                children: 'nodes'
              }">
              <template #default="{ node }">
                <span class="toolbox-group-title" @click="getTemplatesList(node)">
                  <svg-icon-file :icon-class="node.data.icon || 'jiedianguanli'"
                    :style="{ fill: node.data.fill || '#0080ff' }" />
                  <span class="label">{{ node.label }}</span>
                  <div class="outSetBox" @mouseenter.prevent="showBox(node.id)" @mouseleave.prevent="hideBox">
                    <transition name="el-fade-in-linear">
                      <div class="setBox" v-if="showTagId == node.id && boxState && node.isLeaf && node.data.id != 0">
                        <el-icon @click.stop="setTagName(node.data)">
                          <EditPen />
                        </el-icon>
                        <el-icon @click.stop="deleteTag(node.data.id)">
                          <Delete />
                        </el-icon>
                      </div>
                    </transition>
                  </div>
                  <!-- <span v-if="!node.isLeaf" class="tree-node-total numberBox">{{ node.childNodes.length }}</span> -->
                </span>
              </template>
            </el-tree>
          </main>
        </el-col>
        <el-col :span="20" class="rightDataBox">
          <div v-if="listState" class="templateBox">
            <div class="row justify-between">
              <div>
                <el-input v-model="operatorTitle" class="w-50 m-2" style="width: 200px;" placeholder="算子模板名称"
                  @keyup.enter="searchTitle()" />
                <el-button type="primary" size="default" @click="searchTitle()" style="margin: 0 0 0 10px;">{{ $t('search') }}</el-button>
              </div>
              <div>
                <el-button v-if="category_id != 0 && labelAssignData.results.length > 0" type="primary" size="default"
                  @click="sequences()">排序</el-button>
                <el-button type="primary" size="default" @click="openPopup('上传算子', 0)">{{ $t('uploadOperator') }}</el-button>
              </div>
            </div>
            <el-table :data="labelAssignData.results" border style="width: 100%;font-size: 12px;margin-top: 20px;"
              :header-cell-style="{ color: '#333333' }" >
              <el-table-column align="center" prop="id" label="ID" width=" 80" />
              <el-table-column align="center" prop="label" label="模板名称" width="160" show-overflow-tooltip="true">
                <template #default="scope">
                  <el-button link type="primary" @click="toDetailPage(scope.row)">{{
                    scope.row.label
                  }}</el-button>
                </template>
              </el-table-column>
              <el-table-column align="center" prop="operator.version" label="最新版本" width="100" />
              <el-table-column align="center" prop="description" label="描述" />
              <el-table-column align="center" prop="operator.name" label="算子名称" />
              <el-table-column align="center" prop="create_time" label="创建时间" />
              <el-table-column align="center" prop="update_time" label="更新时间" />
              <el-table-column align="center" prop="labels" label="操作" >
                <template #default="{ row }">
                  <el-button link type="primary" size="small" @click="openPopup('更新算子', row.id)">更新</el-button> |
                  <el-button link type="primary" size="small" @click="deleteData(row.id)"
                    style="margin-left: 0;">删除</el-button><span v-if="isSuperAdmin"> | </span>
                  <el-button v-if="isSuperAdmin" link type="primary" style="margin-left: 0;" size="small" @click="publicTemplate(row.id)">公开模板</el-button>
                </template>
              </el-table-column>
              <template #empty>
                <div class="noData">暂无数据</div>
              </template>
            </el-table>
            <div class="row" style="justify-content: end;margin-top: 20px;">
              <el-pagination background layout="total, prev, pager, next" :total=labelAssignData.count style="margin-top: 20px;"
                page-size="10" :current-page="pageData.page" @current-change="changePage" hide-on-single-page="true" />
            </div>
          </div>
          <operator-details @detailSet="detailSet" :template_id="template_id" :updatdOperator="updatdOperator" v-else />
        </el-col>
      </el-row>
      <!-- 上传算子 -->
      <el-dialog v-model="dialogSetData" :title="popupTitle" width="500" :show-close="false"
        @close="resetForm(setDataRef)">
        <box-loading v-if="loading" @click.stop></box-loading>
        <el-form ref="setDataRef" :model="setDataForm" label-position="right" label-width="0" style="max-width: 460px">
          <el-form-item label="">
            <el-upload class="upload-demo uploadBox" drag :http-request="uploadFile" :file-list="uploadFileList" multiple
              :on-change="handleFileChanged" style="width: 100%;" accept=".zip">
              <div class="el-upload__text uploadBoxBtn">
                <el-image :src="imgUrl" fit />
                <el-button type="primary">上传文件</el-button>
                <div>点击上传文件按钮，或拖拽文件到这里</div>
                <div>仅支持上传zip格式文件</div>
              </div>
            </el-upload>
          </el-form-item>
        </el-form>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="resetForm(setDataRef)">取消</el-button>
            <el-button type="primary" @click="createOperator()">
              提交
            </el-button>
          </span>
        </template>
      </el-dialog>
      <!-- 算子排序 -->
      <operator-sort :templatesSort="templatesSort" :category_id="category_id" @emitsFun="emitsFun" />
      <!-- 新增算子分类 -->
      <el-dialog v-model="dialogAddOperator" :title="changeOperatorTitle" width="500" :show-close="false"
        @close="resetOperatorForm(addOperatorRef)">
        <box-loading v-if="loading" @click.stop></box-loading>
        <el-form ref="addOperatorRef" :model="addOperatorForm" :rules="rules" label-position="right" label-width="130px"
          style="max-width: 460px">
          <el-form-item label="名称：" prop="label">
            <el-input v-model.trim="addOperatorForm.label" style="width:300px" placeholder="请输入算子分类名称" />
          </el-form-item>
          <el-form-item label="唯一key：" prop="name">
            <el-input v-model.trim="addOperatorForm.name" style="width:300px" placeholder="由字母、数字、下划线组成" />
          </el-form-item>
          <el-form-item label="描述：" prop="description">
            <el-input v-model.trim="addOperatorForm.description" style="width:300px" placeholder="请输入说明" />
          </el-form-item>
          <el-form-item v-if="changeOperatorTitle!='修改算子分类信息'" label="上级分类:" prop="parent_id">
            <el-select v-model="addOperatorForm.parent_id" class="m-2" placeholder="选择上级分类">
              <el-option v-for="item in optionsList" :key="item.name" :label="item.label" :value="item.id" />
            </el-select>
            <el-tooltip class="box-item" effect="light " content="可选择现有分类作为父级类，若不选则创建新分类" placement="right-start">
              <el-button
                style="transform: scale(.75);transform-origin:left ; margin:0 0 0 10px; font-size: 18px;color: #333;border-color: #333;"
                size="small" circle>?
              </el-button>
            </el-tooltip>
          </el-form-item>
        </el-form>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="resetOperatorForm(addOperatorRef)">取消</el-button>
            <el-button type="primary" @click="addOperatorData(addOperatorRef)">
              提交
            </el-button>
          </span>
        </template>
      </el-dialog>

    </div>
  </q-page>
</template>

<script setup lang="ts">
import { reactive, ref, shallowRef, watch, onUnmounted,onMounted } from "vue";
import { useRouter } from 'vue-router';
import {
  getCategories, postOperators, getTemplates, deleteTemplates,
  putTemplatePublic, postCategories, deleteCategories, putCategories
} from 'src/api/designerTool'
import { dataSetStore } from 'src/stores/dataSet'
import type { FormInstance, FormRules, ElTree } from 'element-plus'
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus';
import SvgIconFile from './svgIconFileManager.vue';
import operatorDetails from './operatorDetails.vue';
import operatorSort from './operatorSort.vue';
import imgUrl from 'assets/dataSet/upload.png'
const router = useRouter()
const pageData = dataSetStore().pageData
const projectId = router.currentRoute.value.params.project_id
const operator = ref('')
const operatorTitle = ref('')
const labelAssignData = shallowRef(
  {
    count: 0,
    next: "",
    previous: "",
    results: []
  }
)
const loading = ref(false)
const treeData = shallowRef(<any>[])
const setDataRef = ref<FormInstance>()
const addOperatorRef = ref<FormInstance>()
const dialogAddOperator = ref(false)
const dialogSetData = ref(false)
const setDataForm = reactive({
  title: '',
  description: '',
})
const addOperatorForm = ref(<any>{
  name: '',
  label: '',
  description: '',
  parent_id: null
})
const uploadFileList: any = ref([])
const fileListArr = ref([])
const paramObj = shallowRef()
const popupTitle = ref('上传算子')
const template_id = ref(0)
const category_id = ref(0)
const listState = ref(true)
const updatdOperator = ref(false)
const templatesSort = ref(false)
const optionsList = ref(<any>[])
const showTagId = ref()
const boxState = ref(false)
const operator_id = ref(0)
const changeOperatorTitle = ref('新增算子分类')
const isSuperAdmin=ref(false)
const treeRef = ref<InstanceType<typeof ElTree>>()
interface Tree {
  [key: string]: any
}
interface objectType {
  [key: string]: string | number | undefined | null | void
}
function openPopup(str: string, id: number) {
  popupTitle.value = str
  dialogSetData.value = true
  template_id.value = id
}
const rules = reactive<FormRules>({
  name: [
    { required: true, message: '分类不能为空', trigger: ['blur', 'change'] }
  ],
  label: [
    { required: true, message: '分类名称不能为空', trigger: ['blur', 'change'] }
  ]
})
onMounted(()=>{
  isSuperAdmin.value=JSON.parse(localStorage.user).is_admin
})

// 上传算子初始化
function initData() {
  uploadFileList.value = []
  paramObj.value = null
  fileListArr.value = []
}
// 获取算子分类信息
categoriesData()
function categoriesData() {
  getCategories(projectId).then((res: any) => {
    optionsList.value = res.data
    let dataArr = [...res.data]
    // let dataArr = res.data.map((row: any) => {
    //   row['label'] = row.description
    //   if (row.nodes.length > 0) {
    //     row.nodes.forEach((nodeItem: any) => {
    //       nodeItem['label'] = nodeItem.description
    //     })
    //   }
    //   return row
    // })
    let addObj = {
      id: 0,
      label: '全部算子'
    }
    dataArr.unshift(addObj)
    treeData.value = dataArr
  }).finally(() => {
    loading.value = false
  })
}
//获取算子模板信息列表
templatesData()
function templatesData() {
  loading.value = true
  let obj = <objectType>{
    ordering: 'sequence'
  }
  if (category_id.value != 0) {
    obj.category_id = category_id.value
  } else {
    delete obj.category_id
  }
  if (operatorTitle.value.length > 0) {
    obj.search = operatorTitle.value
  } else {
    delete obj.search
  }
  obj = Object.assign(obj, pageData)
  getTemplates(projectId, obj).then((res: any) => {
    labelAssignData.value = res.data
  }).finally(() => {
    loading.value = false
  })
}
// 点击筛选模板
function getTemplatesList(node: any) {
  listState.value = true
  category_id.value = node.data.id
  templatesData()
}

// 上传/更新算子
function createOperator() {
  updatdOperator.value = false
  if (fileListArr.value.length == 0) {
    ElMessage.error('请添加算子文件')
    return
  }
  let tipsStr = '上传算子成功'
  if (popupTitle.value == '更新算子') {
    paramObj.value.append("template_id", template_id.value)
    tipsStr = '更新算子成功'
  }
  let obj = paramObj.value
  postOperators(projectId, obj).then((res: any) => {
    ElMessageBox.alert(tipsStr, '提示', {
      confirmButtonText: 'ok',
      autofocus: false
    }).then(() => {
      dialogSetData.value = false
      initData()
      templatesData()
      // 更新详情组件内的数据
      if (!listState.value) {
        updatdOperator.value = true
      }
    })
  }).catch(error => {
    initData()

  }).finally(() => {
    loading.value = false
  })
}
// 删除算子
function deleteData(operator_id: number) {
  ElMessageBox.confirm('确定删除该算子模板吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    loading.value = true
    deleteTemplates(projectId, operator_id).then(() => {
      ElMessage.success('删除成功！')
      templatesData()
    }).finally(() => {
      loading.value = false
    })
  }).catch(() => {
    console.log('cancel delete')
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
  dialogSetData.value = false
}
// 文件上传
function uploadFile(obj: any) {
  paramObj.value = new FormData()
  paramObj.value.append("file", obj.file)
}
// 文件校验
const handleFileChanged = (file: any, fileList: any) => {
  if (fileList.length > 1) {
    fileList.shift()
  }
  fileListArr.value = fileList
  // 检查是否有重复文件
  if (fileList.findIndex((f: any) => f.name === file.name) != fileList.findLastIndex((f: any) => f.name === file.name)) {
    ElMessage.error(file.name + "该文件已存在")
    fileList.pop()
  }
}
// 算子模板详情页
function toDetailPage(node: any) {
  template_id.value = node.id
  listState.value = false
}
//关闭详情页
function detailSet(e: any) {
  if (e == '关闭') {
    listState.value = true
    templatesData()
  }
  if (e == '更新') {
    popupTitle.value = '更新算子'
    dialogSetData.value = true
  }

}
// 算子排序
function sequences() {
  templatesSort.value = true
}
// 公开模板
function publicTemplate(id: number) {
  ElMessageBox.confirm('确定将该算子模板设置为公共模板吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    loading.value = true
    putTemplatePublic(projectId, id).then(() => {
      ElMessage.success('设置成功！')
      // templatesData()
    }).finally(() => {
      loading.value = false
    })
  })
}
function emitsFun(e: any) {
  templatesSort.value = false
  if (e) templatesData()
}
// 搜索算子模板
function searchTitle() {
  templatesData()
}
// 搜索算子
function searchOperator() {
  categoriesData()
}
watch(operator, (val) => {
  treeRef.value.filter(val)
})
const filterNode = (value: string, data: Tree) => {
  if (!value) return true
  return data.label.includes(value)
}
function changePage(currentPage: any) {
  dataSetStore().setPageData(currentPage)
  templatesData()
}
onUnmounted(() => {
  dataSetStore().setPageData(1)
})
// 新增算子列表数据

const resetOperatorForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
  dialogAddOperator.value = false
}

const addOperatorData = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      if (changeOperatorTitle.value == '新增算子分类') {
        postCategories(projectId, addOperatorForm.value).then((res: any) => {
          ElNotification({
            title: 'Success',
            message: '新增算子分类成功',
            type: 'success',
          })
          categoriesData()
        }).catch(error => {
          console.log(error)
        })
      } else {
        putCategories(projectId, operator_id.value, addOperatorForm.value).then((res: any) => {
          ElNotification({
            title: 'Success',
            message: '修改算子分类成功',
            type: 'success',
          })
          categoriesData()
        }).catch(error => {
          console.log(error)
        })
      }
      dialogAddOperator.value = false
    } else {
      console.log('error', fields)
    }
  })
}
// 显示删除和编辑
function showBox(num: number) {
  boxState.value = true
  showTagId.value = num
}
function hideBox() {
  boxState.value = false
}
function openDialogAddOperator() {
  Object.keys(addOperatorForm.value).forEach(key => {
    // console.log(key, addOperatorForm.value[key])
    addOperatorForm.value[key] = ''
  })
  changeOperatorTitle.value = '新增算子分类'
  dialogAddOperator.value = true
}
// 修改算子分类
function setTagName(node: any) {
  changeOperatorTitle.value = '修改算子分类信息'
  const mergedObj = Object.keys(node)
    .filter(key => addOperatorForm.value.hasOwnProperty(key))
    .reduce((result:any, key) => {
      result[key] = node[key]
      return result
    }, {})
  addOperatorForm.value = node
  addOperatorForm.value = mergedObj
  operator_id.value = node.id
  dialogAddOperator.value = true
}
// 删除算子分类
function deleteTag(operator_id: number) {
  ElMessageBox.confirm('确定删除该算子分类吗？', '删除算子分类', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    deleteCategories(projectId, operator_id).then(() => {
      ElMessage.success('删除成功')
      categoriesData()
    }).catch(error => {
      console.log(error)
    })
  })
}

</script>

<style scoped lang="scss">
@import "src/css/designerStyles/index.scss";

.bgBox {
  height: 100%;

  .leftMenus {
    height: calc(100vh - 200px);
    border: 1px solid #ccc;
    border-radius: 3px;
    padding-top: 20px;
    overflow-y: auto;

    &::v-deep .el-input {
      border-radius: 0 !important;
    }

    // height: 100%;
  }

}

.uploadBoxBtn {
  .el-image {
    width: 56px;
    height: 56px;
    display: block;
    margin: 0 auto;
  }
}

.dialog-footer {
  padding-top: 0;
  margin-top: -30px;
}

.toolbox-group-title {
  width: 100%;
  position: relative;
}

.tree-node-total {
  display: inline-block;
  width: 20px;
  height: 20px;
  background: #ddd;
  color: #333;
  border-radius: 50%;
  text-align: center;
  position: absolute;
  right: 0;
}

.changeSort {
  cursor: pointer;

  .el-icon {
    transform: rotateZ(90deg);
    color: #3d5ce4;
    font-size: 14px;
    vertical-align: middle;
  }
}

.outSetBox {
  position: absolute;
  top: 1px;
  right: 1px;
  width: calc(100% - 2px);
  // width: 125px;
  height: calc(100% - 1px);
  border-radius: 3px;
  overflow: hidden;
  border: 1px solid rgba(61, 90, 228, 0);
  text-align: right;
}

.setBox {
  width: 100%;
  background: linear-gradient(to right, rgba(255, 255, 255, 0.3) 30%, rgba(255, 255, 255, 1));
  text-align: center;
  display: flex;
  justify-content: flex-end;
  height: inherit;
  align-items: center;
  border-radius: 4px;

  .el-icon {
    margin-right: 10px;
    font-size: 18px;
    cursor: pointer;

    &:hover {
      color: #3D5CE4;
    }

    &:last-child {
      &:hover {
        color: #FF5656;
      }
    }
  }
}
</style>
